package modifyx

import (
	"gitee.com/zhongguo168a/gocodes/datax/convertx"
)

// 新建一个对象
func NewObject(root *Root) (obj *Object) {
	obj = newObject()
	obj.root = root
	return
}

func newObject() (obj *Object) {
	obj = &Object{}
	obj.temps = map[string]interface{}{}
	return
}

// 修正对象
// 如果需要在运行时，替换源的数据，可通过设置runtime实现
type Object struct {
	root *Root
	// 字段的路径
	path string
	// 在父对象中的字段名字
	field string
	// 缓存的map/array/struct等对象, 避免重复创建对象
	temps map[string]interface{}
	//
	creators map[string]func(obj IObject) IObject
	creator  func(obj IObject) IObject
}

func (s *Object) RefClassCreator(field string, creator func(object IObject) IObject) {
	if s.creators == nil {
		s.creators = map[string]func(obj IObject) IObject{}
	}
	s.creators[field] = creator
}

func (s *Object) RefOriginBool(field string) bool {
	return convertx.AnyToBool(s.root.source.GetOrigin(s.path + "/" + field))
}

func (s *Object) RefOriginFloat(field string) float64 {
	return convertx.AnyToFloat64(s.root.source.GetOrigin(s.path + "/" + field))
}
func (s *Object) RefOriginInt(field string) int {
	return convertx.AnyToInt(s.root.source.GetOrigin(s.path + "/" + field))
}

func (s *Object) RefAnyType() string {
	return convertx.AnyToString(s.root.source.GetOrigin(s.path + "/_type"))
}

func (s *Object) Dispose() {
	s.temps = nil
	s.root = nil
}

// 修正后的整型
func (s *Object) RefInt(field string) int {
	root := s.root
	return convertx.AnyToInt(root.source.Get(root.ctx, s.path+"/"+field))

}

// 修正后的整型
func (s *Object) RefBool(field string) bool {
	root := s.root
	return convertx.AnyToBool(root.source.Get(root.ctx, s.path+"/"+field))
}

// 修正后的浮点型
func (s *Object) RefFloat64(field string) float64 {
	root := s.root
	return convertx.AnyToFloat64(root.source.Get(root.ctx, s.path+"/"+field))

}

// 获取原始数据指定的字段
func (s *Object) RefOrigin(field string) interface{} {
	return s.root.source.GetOrigin(field)
}

func (s *Object) RefUint(field string) (val uint) {
	return uint(s.RefInt(field))
}

func (s *Object) RefString(field string) (val string) {
	root := s.root
	return convertx.AnyToString(root.source.Get(root.ctx, s.path+"/"+field))
}
func (s *Object) RefAny(field string) (val interface{}) {
	return s.RefObject(field)
}
func (s *Object) RefArray(field string) (r IArray) {
	iobj, hastemp := s.temps[field]
	if hastemp == false {
		obj := newArray()
		obj.root = s.root
		obj.path = s.path + "/" + field
		obj.creator = s.creators[field]
		//
		iobj = obj
		s.temps[field] = iobj
	}

	r = iobj.(IArray)
	return
}

func (s *Object) RefMap(field string) (r IObject) {
	iobj, hastemp := s.temps[field]
	if hastemp == false {
		obj := newObject()
		obj.root = s.root
		obj.field = field
		obj.path = s.path + "/" + field
		obj.temps = map[string]interface{}{}
		//
		creator, hascreator := s.creators[field]
		if hascreator {
			obj.creator = creator
		}
		iobj = obj
		s.temps[field] = iobj
	}

	r = iobj.(IObject)
	return
}

func (s *Object) RefObject(field string) (r IObject) {
	iobj, hastemp := s.temps[field]
	if hastemp == false {
		obj := newObject()
		obj.root = s.root
		obj.field = field
		obj.path = s.path + "/" + field
		obj.temps = map[string]interface{}{}

		if s.creator != nil { // 只有map对象会有此属性
			iobj = s.creator(obj)
		} else {
			//
			creator, hascreator := s.creators[field]
			if !hascreator {
				if obj.RefAnyType() != "" {
					creator = getType(obj.RefAnyType())
					if creator != nil {
						iobj = creator(obj)
					} else {
						iobj = obj
					}
				} else {
					iobj = obj
				}
			} else {
				iobj = creator(obj)
			}
		}

		s.temps[field] = iobj
	}

	r = iobj.(IObject)
	return
}

func (s *Object) RefIsNil() bool {
	source := s.root.source
	return source.IsNil(s.path)
}

func (s *Object) RefLength() int {
	source := s.root.source
	return source.Length(s.path)
}

func (s *Object) RefKeys() (r []string) {
	if s.RefIsNil() {
		return
	}

	source := s.root.source
	return source.MapKeys(s.path)
}
